﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using HYView;

namespace HYRElectric.WirePlace
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	public class CmdPanelConnection : IExternalCommand
	{
		public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			this.uiDoc = cmdData.Application.ActiveUIDocument;
			this.choices = this.uiDoc.Selection;
			this.v = this.uiDoc.ActiveView.Document.ActiveView;
			this.m_Level = this.v.GenLevel;
			if (!(this.v is ViewPlan))
			{
				Result result = SwitchView.SetUsableView(CmdViewType.FloorPlan, cmdData);
				if (result != Result.Succeeded)
				{
					return result;
				}
			}
			this.ct = this.GetCableTrayType();
			if (this.ct == null)
			{
				MessageBox.Show("当前项目中未找到箱柜连接时所使用的桥架，请先加载桥架。", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			Transaction transaction = new Transaction(this.uiDoc.Document, "PanelConnection");
			using (DlgPanelConnection dlgPanelConnection = new DlgPanelConnection())
			{
				DialogResult dialogResult = dlgPanelConnection.ShowDialog();
				if (dialogResult == DialogResult.Cancel)
				{
					return Autodesk.Revit.UI.Result.Cancelled;
				}
				if (dialogResult == DialogResult.OK)
				{
					transaction.Start();
					double num = this.ct.get_Parameter(BuiltInParameter.CABLETRAY_MINBENDMULTIPLIER_PARAM).AsDouble() * 2.0;
					this.width = Convert.ToDouble(dlgPanelConnection.txtWidth.Text.Trim());
					this.height = Convert.ToDouble(dlgPanelConnection.txtHeight.Text.Trim());
					this.level = AssistFunc.mmToFeet(Convert.ToDouble(dlgPanelConnection.txtLevel.Text.Trim()));
					try
					{
						Category category = this.uiDoc.Document.Settings.Categories.get_Item(BuiltInCategory.OST_CableTray);
						this.uiDoc.Document.ActiveView.SetYJKVisibility(category, true);
						Reference reference = this.choices.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new CmdPanelConnection.NewPanelFilter(), "请选择要连接的配电柜");
						FamilyInstance familyInstance = this.uiDoc.Document.GetElement(reference) as FamilyInstance;
						Reference reference2 = this.choices.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new CmdPanelConnection.NewPanelFilter(), "请选择要连接的配电柜");
						FamilyInstance familyInstance2 = this.uiDoc.Document.GetElement(reference2) as FamilyInstance;
						Connector panelConn = this.GetPanelConn(familyInstance);
						Connector panelConn2 = this.GetPanelConn(familyInstance2);
						if (panelConn == null || panelConn2 == null)
						{
							MessageBox.Show("连接失败，请检查所选箱柜是否有桥架连接件。", "盈建科提示");
							transaction.RollBack();
							return Autodesk.Revit.UI.Result.Cancelled;
						}
						XYZ origin = panelConn.Origin;
						XYZ origin2 = panelConn2.Origin;
						XYZ pEnd = new XYZ(origin.X, origin2.Y, this.level);
						if (Math.Abs(origin.X - origin2.X) < num)
						{
							CableTray cableTray = this.CreateCableTray(origin, origin2, "Top");
							if (!this.CreateCableTrayOneSide(origin, cableTray, false, 0))
							{
								transaction.RollBack();
								return Autodesk.Revit.UI.Result.Cancelled;
							}
							this.CreateCableTrayOneSide(origin2, cableTray, false, 1);
						}
						else if (Math.Abs(origin.Y - origin2.Y) < num)
						{
							CableTray cableTray2 = this.CreateCableTray(origin, origin2, "Top");
							if (!this.CreateCableTrayOneSide(origin, cableTray2, true, 0))
							{
								transaction.RollBack();
								return Autodesk.Revit.UI.Result.Cancelled;
							}
							this.CreateCableTrayOneSide(origin2, cableTray2, true, 1);
						}
						else
						{
							try
							{
								CableTray cableTray3 = this.CreateCableTray(origin, pEnd, "Top");
								if (!this.CreateCableTrayOneSide(origin, cableTray3, false, 0))
								{
									transaction.RollBack();
									return Autodesk.Revit.UI.Result.Cancelled;
								}
								CableTray cableTray4 = this.CreateCableTray(origin2, pEnd, "Top");
								this.CreateCableTrayOneSide(origin2, cableTray4, true, 0);
								if (!this.CreateElbow(cableTray3, cableTray4, false))
								{
									transaction.RollBack();
									return Autodesk.Revit.UI.Result.Cancelled;
								}
							}
							catch (Exception)
							{
							}
						}
						transaction.Commit();
					}
					catch (Exception)
					{
						transaction.RollBack();
					}
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private bool CreateCableTrayOneSide(XYZ pt, CableTray cableTray, bool rotate, int i)
		{
			LocationCurve locationCurve = cableTray.Location as LocationCurve;
			CableTray ct = this.CreateCableTray(pt, locationCurve.Curve.GetEndPoint(i), "Side");
			return this.CreateElbow(ct, cableTray, rotate);
		}

		private CableTray CreateCableTray(XYZ pStart, XYZ pEnd, string type)
		{
			CableTray cableTray;
			if (type == "Top")
			{
				cableTray = CableTray.Create(this.uiDoc.ActiveView.Document, this.ct.Id, new XYZ(pStart.X, pStart.Y, this.level), new XYZ(pEnd.X, pEnd.Y, this.level), this.m_Level.Id);
				cableTray.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).Set(this.level);
			}
			else
			{
				cableTray = CableTray.Create(this.uiDoc.ActiveView.Document, this.ct.Id, pStart, pEnd, this.m_Level.Id);
			}
			cableTray.get_Parameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM).Set(AssistFunc.mmToFeet(this.width));
			cableTray.get_Parameter(BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM).Set(AssistFunc.mmToFeet(this.height));
			return cableTray;
		}

		private bool CreateElbow(CableTray ct1, CableTray ct2, bool rotate)
		{
			IList<XYZ> list = new List<XYZ>();
			IList<Connector> list2 = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = ct1.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				list.Add(connector.Origin);
				list2.Add(connector);
			}
			IList<XYZ> list3 = new List<XYZ>();
			IList<Connector> list4 = new List<Connector>();
			ConnectorSetIterator connectorSetIterator2 = ct2.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator2.MoveNext())
			{
				object obj2 = connectorSetIterator2.Current;
				Connector connector2 = obj2 as Connector;
				list3.Add(connector2.Origin);
				list4.Add(connector2);
			}
			Line line = YJKLineEx.YJKGetBound(list.ElementAt(0), list.ElementAt(1));
			Curve curve = YJKLineEx.YJKGetBound(list3.ElementAt(0), list3.ElementAt(1));
			line.MakeUnbound();
			curve.MakeUnbound();
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			SetComparisonResult setComparisonResult = line.Intersect(curve, out intersectionResultArray);
			XYZ xyz = null;
            if ((SetComparisonResult)(SetComparisonResult)4 != setComparisonResult && !intersectionResultArray.IsEmpty)
			{
				xyz = intersectionResultArray.get_Item(0).XYZPoint;
			}
			Connector connector3 = list2.ElementAt(0);
			if (xyz.DistanceTo(list.ElementAt(0)) > xyz.DistanceTo(list.ElementAt(1)))
			{
				connector3 = list2.ElementAt(1);
			}
			Connector connector4 = list4.ElementAt(0);
			if (xyz.DistanceTo(list3.ElementAt(0)) > xyz.DistanceTo(list3.ElementAt(1)))
			{
				connector4 = list4.ElementAt(1);
			}
			if (connector3 != null && connector4 != null)
			{
				try
				{
					if (rotate)
					{
						Line line2 = YJKLineEx.YJKGetUnBound(connector3.Origin, XYZ.BasisZ);
						ct1.Location.Rotate(line2, Math.PI*.5);
					}
					connector3.ConnectTo(connector4);
					this.uiDoc.ActiveView.Document.Create.NewElbowFitting(connector3, connector4);
					return true;
				}
				catch
				{
					MessageBox.Show("连接失败，请检查\"" + ct1.Name + "\"的类型属性中是否包含了桥架弯头配件。", "盈建科提示");
					return false;
				}
				return false;
			}
			return false;
		}

		private Connector GetPanelConn(FamilyInstance familyInstance)
		{
			Connector result = null;
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = familyInstance.MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
                if (connector.Domain == (Autodesk.Revit.DB.Domain)4 && connector.Shape == (ConnectorProfileType)1 && connector.ConnectorType != (ConnectorType)32)
				{
					list.Add(connector);
				}
			}
			if (list.Count > 0)
			{
				try
				{
					result = (from c in list
					orderby c.Origin.Z descending
					select c).ToList<Connector>()[0];
				}
				catch
				{
				}
			}
			return result;
		}

		private CableTrayType GetCableTrayType()
		{
			IList<Element> list = new FilteredElementCollector(this.uiDoc.ActiveView.Document).OfClass(typeof(CableTrayType)).ToElements();
			List<CableTrayType> list2 = new List<CableTrayType>();
			foreach (Element element in list)
			{
				CableTrayType cableTrayType = (CableTrayType)element;
                if (cableTrayType.ShapeType == (CableTrayShape)1)
				{
					if (cableTrayType.get_Parameter(BuiltInParameter.ALL_MODEL_FAMILY_NAME).AsString() == "无配件的电缆桥架")
					{
						return cableTrayType;
					}
					list2.Add(cableTrayType);
				}
			}
			if (list2.Count > 0)
			{
				return list2[0];
			}
			if (list.Count > 0)
			{
				return list[0] as CableTrayType;
			}
			return null;
		}

		private UIDocument uiDoc;

		private Selection choices;

        private Autodesk.Revit.DB.View v;

		private Level m_Level;

		private double width;

		private double height;

		private double level;

		private CableTrayType ct;

		private class NewPanelFilter : ISelectionFilter
		{
			public bool AllowElement(Element element)
			{
				if (element.Category.Id.IntegerValue.ToString() == "OST_ElectricalEquipment")
				{
					ConnectorSetIterator connectorSetIterator = (element as FamilyInstance).MEPModel.ConnectorManager.Connectors.ForwardIterator();
					while (connectorSetIterator.MoveNext())
					{
						if ((connectorSetIterator.Current as Connector).Domain == (Autodesk.Revit.DB.Domain)4)
						{
							return true;
						}
					}
				}
				return false;
			}

			public bool AllowReference(Reference refer, XYZ point)
			{
				return false;
			}
		}
	}
}
